#include <bits/stdc++.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

using namespace std;

typedef struct Node{
	int id;
	uint money;
	bool operator<(const Node &other)const{
		return id<other.id;
	}
	bool operator==(const Node &other)const{
		return id==other.id;
	}
}Node;

string testFile = "/data/test_data.txt";
string resultFile = "/projects/student/result.txt";
int account_num = 0;
uint inputs[2*2000000];
uint accts[2*2000000];
vector<Node> G[2000000];
vector<int> RG[2000000];
int ans3[10000000][3], p3=0;
int ans4[10000000][4], p4=0;
int ans5[10000000][5], p5=0;
int ans6[20000000][6], p6=0;
int ans7[20000000][7], p7=0;
bool vis[2000000];
int avl[2000000];
int p[7];
char account_chars[2000000][12];
short length[2000000];
char buf[77*20000000];

uint parse_1(char** s){
	char *p = *s;
	uint val = *(p++) - '0';
	while(*p != ',') val = 10*val + *(p++) - '0';
	*s = p+1;
	return val;
}
uint parse_2(char** s){
	char *p = *s;
	uint val = *(p++) - '0';
	while(*p != '\r' && *p != '\n') val = 10*val + *(p++) - '0';
	*s = *p=='\r' ? p+2:p+1;
	return val;
}

void loadData_and_createGrap(){
	int fd = open(testFile.c_str(), O_RDONLY);
    int size = lseek(fd, 0, SEEK_END);
    char* p_map =(char*)mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
    close(fd);
	char *p = p_map;
	int n=0;//n表示文件中的记录数
	uint money[2000000];
	while(*p != '\0'){
		inputs[n]=parse_1(&p);
		inputs[n+2000000]=parse_1(&p);
		money[n++]=parse_2(&p);
	}
	memcpy(accts, inputs, 4*n);
	memcpy(accts+n, inputs+2000000, 4*n);  
	sort(accts, accts+2*n);//排序
	account_num = unique(accts, accts+2*n) - accts;//去重
	unordered_map<uint, int> idHash;
	for(int i=0; i<account_num; i++)idHash[accts[i]]=i;
	Node node;
	for(int i=0,a=0,b=0, m=0; i<n; i++){
		a=idHash[inputs[i+0]];
		b=idHash[inputs[i+2000000]];
		if(a==b){m++;continue;}
		G[a].push_back(Node{b,money[m++]});
		RG[b].push_back(a);
	}
	for(int i=0; i<account_num; i++) sort(G[i].begin(),G[i].end());
	munmap(p_map, size);
}

void parse_to_char(uint a, char *tmp, int &k){
	int n=0;
	do{tmp[n++] = a%10+'0';}while((a/=10)>0);
	reverse(tmp, tmp+n);
	tmp[n++]=',';
	length[k]=n;
}

void save(){
	int n=sprintf(buf,"%d\n",p3+p4+p5+p6+p7);
	int i, j, v;
	for(i=0; i<account_num; i++) parse_to_char(accts[i], account_chars[i], i);
	for(i=0; i<p3; i++){
		for(j=0; j<3; j++){
			v=ans3[i][j];
			memcpy(buf+n, account_chars[v], length[v]);
			n+=length[v];
		}
		buf[n-1]='\n';
	}
	for(i=0; i<p4; i++){
		for(j=0; j<4; j++){
			v = ans4[i][j];
			memcpy(buf+n, account_chars[v], length[v]);
			n+=length[v];
		}
		buf[n-1]='\n';
	}
	for(i=0; i<p5; i++){
		for(j=0; j<5; j++){
			v = ans5[i][j];
			memcpy(buf+n, account_chars[v], length[v]);
			n+=length[v];
		}
		buf[n-1]='\n';
	}
	for(i=0; i<p6; i++){
		for(j=0; j<6; j++){
			v = ans6[i][j];
			memcpy(buf+n, account_chars[v], length[v]);
			n+=length[v];
		}
		buf[n-1]='\n';
	}
	for(i=0; i<p7; i++){
		for(j=0; j<7; j++){
			v = ans7[i][j];
			memcpy(buf+n, account_chars[v], length[v]);
			n+=length[v];
		}
		buf[n-1]='\n';
	}
	int fd = open(resultFile.c_str(), O_RDWR|O_CREAT, 0666);
	lseek(fd, n-1, SEEK_SET);
	write(fd, "", 1);
	char* p_map =(char*)mmap(NULL, n, PROT_WRITE, MAP_SHARED, fd, 0);
	memcpy(p_map, buf, n);
	munmap(p_map, n);
	close(fd);
}

inline bool check(const uint &x, const uint &y){
	return x<=5ll*y && y<=3ll*x;
}

uint ftrans;//first transfer money
void dfs(int &head, int &cur, Node &last, int dep){
	uint money = dep > 1 ? last.money:0;
	p[dep-1]=cur;
	int v;
	for(Node &each:G[cur]){
		if(dep==1) ftrans=each.money;//记下这第一笔转账
		if(dep>1 && !check(last.money, each.money)) continue;
		v = each.id;
		if(v==head && dep>2){
			if(check(each.money, ftrans)){
				switch(dep){
					case 3:
						memcpy(ans3[p3++], p, 12);
						break;
					case 4:
						memcpy(ans4[p4++], p, 16);
						break;
					case 5:
						memcpy(ans5[p5++], p, 20);
						break;
					case 6:
						memcpy(ans6[p6++], p, 24);
						break;
				}
			}
			continue;
		}
		if(dep==6 || avl[v]!=head || vis[v]) continue;
		vis[cur] = true;
		dfs(head, v, each, dep+1);
		vis[cur] = false;
	}
}

void dfs1(int &head, int &cur, int dep){
	int v;
	for(Node &each:G[cur]){
		v = each.id;
		if(v < head || vis[v]) continue;
		avl[v] = head;
		if(dep == 2) continue;
		vis[cur] = true;
		dfs1(head, v, dep+1);
		vis[cur] = false;
	}
}

void dfs2(int &head, int &cur, int dep){
	for(int &v:RG[cur]){
		if(v < head || vis[v]) continue;
		avl[v] = head;
		if(dep == 3) continue;
		vis[cur] = true;
		dfs2(head, v, dep+1);
		vis[cur] = false;
	}
}

void loop(int &u){
	p[0]=u;
	int v1,v2,v3,v4,v5,v6;
	vector<Node>::iterator node7;
	for(Node &node1:G[u]){
		v1=node1.id; if(avl[v1]!=u) continue; ftrans = node1.money;
		for(Node &node2:G[v1]){
			v2=node2.id; if(avl[v2]!=u || !check(node1.money, node2.money)) continue;
			for(Node &node3:G[v2]){
				v3=node3.id; if(v3<u || v3==v1 || v3==u || !check(node2.money, node3.money)) continue;
				for(Node &node4:G[v3]){
					v4=node4.id; if(avl[v4]!=u || v4==v2 || v4==v1 || !check(node3.money, node4.money)) continue;
					for(Node &node5:G[v4]){
						v5=node5.id; if(avl[v5]!=u || v5==v3 || v5==v2 || v5==v1  || !check(node4.money, node5.money)) continue;
						for(Node &node6:G[v5]){
							v6=node6.id; if(avl[v6]!=u) continue;
							if(v6==v1 || v6==v2 || v6==v3 || v6==v4 || !check(node5.money, node6.money)) continue;
							node7 = find(G[v6].begin(),G[v6].end(), Node{u,0});
							if(node7==G[v6].end() || !check(node6.money, node7->money)) continue;
							if(!check(node7->money, ftrans)) continue;
							p[1]=v1;
							p[2]=v2;
							p[3]=v3;
							p[4]=v4;
							p[5]=v5;
							p[6]=v6;
							memcpy(ans7[p7++], p, 28);
						}
					}
				}
			}
		}
	}
}

void solve(){
	memset(vis, 0, sizeof(vis));
	memset(avl, -1, sizeof(avl));
	Node tmp;
	for(int i=0;i<account_num;i++){
		if(G[i].size()!=0 && RG[i].size()!=0){
			dfs1(i,i,1);
			dfs2(i,i,1);
			dfs(i,i,tmp,1);
			loop(i);
		}
	}
}

int main(int argc, char* argv[]){
	loadData_and_createGrap();
	solve();
	save();
	exit(0);
}